import { Warning } from '@brillout/docpress'

<Warning>
Vike will probably deprecate support for user-land CJS code soon. (Using CJS packages will still be supported for the foreseeable future.)

If you have a use case that requires the source code of your Vike app to be written in CJS then let us know and we'll consider not deprecating it. We would then create a new setting `disableCJSWarning` instead.
</Warning>

While you can use Vike with
[CJS](https://nodejs.org/api/modules.html#modules-commonjs-modules:~:text=CommonJS%20modules%20are%20the%20original%20way%20to%20package%20JavaScript%20code%20for%20Node.js.%20Node.js%20also%20supports%20the%20ECMAScript%20modules%20standard%20used%20by%20browsers%20and%20other%20JavaScript%20runtimes.),
we recommend using
[ESM](https://nodejs.org/api/esm.html#modules-ecmascript-modules:~:text=ECMAScript%20modules%20are%20the%20official%20standard%20format%20to%20package%20JavaScript%20code%20for%20reuse.%20Modules%20are%20defined%20using%20a%20variety%20of%20import%20and%20export%20statements.)
instead.

> Most of your code should already be ESM, as code processed by Vite is always ESM. But [some of your server code may not be processed by Vite](https://github.com/vikejs/vike/issues/562) and may be CJS.

If you get the following warning:

```
[vike][Warning] We recommend setting package.json#type to "module"
```

Then, in order to remove the warning, add this to your `package.json`:

```json5
// package.json
{
   // ...
   type: "module"
}
```

This [makes Node.js treat all .js files as ESM](https://nodejs.org/docs/latest-v13.x/api/esm.html#esm_package_json_type_field:~:text=Files%20ending%20with%20.js%20will%20be%20loaded%20as%20ES%20modules%20when%20the%20nearest%20parent%20package.json%20file%20contains%20a%20top%2Dlevel%20field%20%22type%22%20with%20a%20value%20of%20%22module%22.).

If you have .js files written in CJS then migrate them to ESM, for example:

```js
// CJS code // [!code --]
const express = require('express') // [!code --]
const { renderPage } = require('vike/server') // [!code --]
// ESM code // [!code ++]
import express from 'express' // [!code ++]
import { renderPage } from 'vike/server' // [!code ++]
```

> An escape hatch is to use [the `.cjs` and `.mjs` file extensions](https://nodejs.org/api/esm.html#enabling:~:text=Authors%20can%20tell%20Node.js%20to%20use%20the%20ECMAScript%20modules%20loader%20via%20the%20.mjs%20file%20extension): it enables you to choose between CJS and ESM on a file-by-file basis (regardless of `package.json#type`).


## TypeScript migration

Depending on your setup, you may need to append `.js` to the path of your imports:

```ts
// someTypeScriptFile.ts

import { something } from './some/module' // [!code --]
import { something } from './some/module.js' // [!code ++]
```

You can use [this script](https://gist.github.com/brillout/79fd8b21e8893f92334b885ee9fa30ff) to automatically apply this change.

> This is typically only needed for library code (e.g. your monorepo packages used by your application code). For the application code itself, you can use [TypeScript's new `--moduleResolution bundler` option](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#moduleresolution-bundler) instead.


## Monorepo migration

If you aren't using a monorepo, then migrating the source code of your Vike app from CJS to ESM is usually straightforward.

Even if you use a monorepo that uses a mix of ESM/CJS packages, the migration of your Vike app is still straightforward: usually there aren't any monorepo package that depends on your Vike app. (In other words, your Vike app is a root in your monorepo dependency graph.)

That said, migrating your whole monorepo isn't easy: the issue is that CJS modules cannot (easily) import ESM modules.

> Node.js 22 added support for `require()`'ing ES modules behind a `--experimental-require-module` flag, see [Node.js Blog > Node.js 22 is now available! > Support require()ing synchronous ESM graphs](https://nodejs.org/en/blog/announcements/v22-release-announce#support-requireing-synchronous-esm-graphs).
>
> This means you can use Node.js 22 and ignore the following recommendation.

But because ESM modules can import CJS modules (unlike the opposite), a sensible strategy is to migrate your monorepo in a top-down fashion: first migrate CJS modules that aren't required by other CJS modules.

For example, you can usually starting migrating your Vike app and then later migrate its monorepo dependencies.

You can use a script to help determine what package in your monorepo is a candidate for CJS->ESM migration. For example:
 - [check-esm.js](https://gist.github.com/ChristophP/2c0082f6944fae6d0a15e99b2dfb5423)
   > Basically it uses some rush tools to figure out which packages are already using type module. It fails if there are any packages that aren't whitelisted that are not type module yet. It also prints an overview like this to show which packages are still used in CJS packages. Once a package is not used in CJS packages it's green and good to migrate.
   <img src="https://i.imgur.com/xRscY2r.png" />

> Contributions welcome to share your script.
